﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Scala.Data.Impl;
using Scala.Logic.Repositories;
using Scala.Data;
using Scala.Logic;
using Scala.Logic.Services;

namespace Scala.UI
{
    public partial class Main : Form
    {
        IEventRepo eventRepo;
        IEventTypeRepo eventTypeRepo;
        IUnitOfWorkFactory factory;
        EventTypeValidation eventTypeValidator = new EventTypeValidation();
        EventValidator eventValidator = new EventValidator();
        InputStringsService inputService = new InputStringsService();
        XMLService xmlService = new XMLService();

        protected Main()
        {
            InitializeComponent();           
        }

        public Main(IEventRepo eventRepo, IEventTypeRepo eventTypesRepo, IUnitOfWorkFactory factory) : this()
        {
            this.eventRepo = eventRepo;
            this.eventTypeRepo = eventTypesRepo;
            this.factory = factory;         
        }

        /// <summary>
        /// Get mounthed events
        /// </summary>
        /// <returns></returns>
        private List<Event> GetMounthedEvents(DateTime date)
        {
            using (var uow = factory.Create())
            {
                return eventRepo.GetMounthedRecordsBydate(date).ToList();                
            }
        }

        /// <summary>
        /// Get all events
        /// </summary>
        /// <returns></returns>
        private List<Event> GetEvents()
        {
            using (var uow = factory.Create())
            {
                return eventRepo.FindRange(x => true).ToList();
            }
        }

        /// <summary>
        /// Get all event types
        /// </summary>
        /// <returns></returns>
        private List<EventType> GetEventTypes()
        {
            using (var uow = factory.Create())
            {
                return eventTypeRepo.FindRange(x => true).ToList();
            }
        }

        /// <summary>
        /// Get events sorted by event type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private List<Event> GetSortedByEvent(EventType type)
        {
            using (var uow = factory.Create())
            {
                return eventRepo.GetNextsWithAType(type).ToList();
            }
        }

        /// <summary>
        /// Get concrete event type
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private EventType GetEventType(int id)
        {
            using (var uow = factory.Create())
            {
                return eventTypeRepo.Get(id);
            }
        }

        /// <summary>
        /// get concrete event
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private Event GetEvent(int id)
        {
            using (var uow = factory.Create())
            {
                return eventRepo.Get(id);
            }
        }

        /// <summary>
        /// Save event type with validation
        /// </summary>
        /// <remarks>If invalid object, Message box with problem is shown</remarks>
        /// <param name="eventType"></param>
        private void Save(EventType eventType)
        {
            var error = String.Empty;
            var valid = eventTypeValidator.Validate(eventType, out error);
            if (valid)
            {
                using (var uow = factory.Create())
                {
                    eventTypeRepo.Save(eventType);
                }
            }
            else
            {
                MessageBox.Show(error);
            }
        }

        /// <summary>
        /// Save event with validation
        /// </summary>
        /// <remarks>Verification on input strings + null or empty properties
        /// Additional verification with regex pattern
        /// And finaly cross referenced types with period</remarks>
        /// <param name="someEvent"></param>
        public void Save(Event someEvent)
        {
            var error = String.Empty;
            var valid = eventValidator.Validate(someEvent, out error);
            if (!valid) { MessageBox.Show(error); return; }

            if (!inputService.ValidateEventPlaceFacade(someEvent.Place))
            { MessageBox.Show("Invalid place. Only cyr with spacebar"); return; }
            if (!inputService.ValidateEventTitleFacade(someEvent.Title))
            { MessageBox.Show("Invalid title. \n 3-200 lenght and not punct starts symbol"); return; }

            using (var uow = factory.Create())
            {
                if (eventRepo.CountOfCrossDateEvents
                    (someEvent.FromDate, someEvent.TillDate, someEvent.EventType) != 0)
                {
                    //already planned events with type and period
                    var res = MessageBox.Show(
                        "There is already planned event with such type during the period \n Do you want add event in any case?",
                        "My Application", MessageBoxButtons.YesNo);
                    if (res == System.Windows.Forms.DialogResult.No)
                        return;
                }
                eventRepo.Save(someEvent);
            }
        }

        /// <summary>
        /// Export XML file with schema validation
        /// <remarks>If invalid file occurs, messagemox is shown</remarks>
        /// </summary>
        public void ExportXMLTenRecords()
        {
            using(var uow = factory.Create())
            {
                var records = eventRepo.GetNexts(10);
                var xmlDocument = xmlService.SerializeToXML(records.ToList());
                if (!xmlService.Validate(xmlDocument))
                {
                    MessageBox.Show("Invalid xml file with resources scheme");
                }
                else
                {
                    //show or save document
                }
            }
        }
    }
}
